package com.xdjd.mobile.business.util;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.regex.Pattern;

/**
 * @Description:公共字符串工具类
 * @Author:panjl
 * @Since:2014年12月29日上午9:43:23
 */
public class CommonStringUtil {

    private static final Logger logger = LoggerFactory.getLogger(CommonStringUtil.class);

    public static int getLengthStr(String str) {
        int length = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (((int) c) > 127)
                length += 2;
            else
                length += 1;
        }
        return length;
    }

    public static String getOperatorStr(String mobileNo) {
        String mobileRegex = "^1((3[5-9]|47|5[0-2,7-9]|8[7,8])[0-9]|34[0-8])[0-9]{7}$";
        String unicomRegex = "^1(3[0-2]|45|5[5,6]|8[5,6])[0-9]{8}$";
        String telecomRegex = "^1(([3,5]3|8[0,9])[0-9]|349)[0-9]{7}$";
        if (Pattern.compile(mobileRegex).matcher(mobileNo).matches())
            return "Y";
        if (Pattern.compile(unicomRegex).matcher(mobileNo).matches())
            return "L";
        if (Pattern.compile(telecomRegex).matcher(mobileNo).matches())
            return "D";
        return null;
    }

    public static boolean checkTelNumber(String telNo) {
        return Pattern.compile("^1[3,5,8]\\d{9}$").matcher(telNo).matches();
    }

    public static String getFormatDateStr(String format, Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * @throws
     * @方法名：getSessionId
     * @功能描述：生成sessionid 格式：14位时间+6位随机数
     * @创建人：leo
     * @创建时间：2012-8-10 上午11:41:43
     * @参数：@return
     * @返回：String
     */
    public static String getSessionId() {
        return getFormatDateStr("yyyyMMddHHmmss", new Date()) + randomInt(6);
    }

    /**
     * @param message
     * @return
     * @Methodname mobileReplace
     * @Description 手机号码中间四位隐藏
     * @author liull
     * @date 2014年3月31日下午1:30:04
     */
    public static String mobileReplace(String message) {
        String mobile = "";
        if (null != message && !"".equals(message) && message.length() > 7) {
            mobile = message.substring(0, 3) + "****" + message.substring(7);
        }
        return mobile;
    }

    /**
     * @param message
     * @return
     * @Methodname mobileReplace
     * @Description 名字隐藏
     * @author liull
     * @date 2014年3月31日下午1:30:04
     */
    public static String nameReplace(String message) {
        String name = "";
        if (null != message && !"".equals(message) && message.length() >= 2) {
            if (message.length() >= 3) {
                name = message.substring(0, 1) + "*" + message.substring(2, 3);
            } else {
                name = message.substring(0, 1) + "*" + message.substring(2);
            }
        }
        return name;
    }

    /**
     * @param message
     * @return
     * @Methodname mobileReplace
     * @Description 身份证隐藏
     * @author liull
     * @date 2014年3月31日下午1:30:04
     */
    public static String idNoReplace(String message) {
        String idNo = "";
        if (null != message && !"".equals(message) && message.length() >= 18) {
            idNo = message.substring(0, 4) + "**********" + message.substring(14);
        }
        return idNo;
    }


    public static String UrlDecodeAndBase64Decode(String data) {
        try {
            return new String(URLDecoder.decode(data, "UTF-8"));
        } catch (Exception e) {
            logger.error("编码失败", e);
            return data;
        }
    }

    private static final int DEFAULT_SCALE = 6; // 保留小数位
    private static final double EARTH_RADIUS = 6371004; // 米
    private static final double RAD = Math.PI / 180.0;

    /**
     * @throws
     * @方法名：getAround
     * @功能描述：获取某点指定半径的正东单西北的位置
     * @创建人：leo
     * @创建时间：2012-12-5 上午11:20:11
     * @参数：@param lon 经度
     * @参数：@param lat 纬度
     * @参数：@param radius 半径
     * @参数：@return
     * @返回：double[]
     */
    public static double[] getAround(double lon, double lat, double radius) {
        // 同经度，纬度相差一度 距离差值 πR/180
        BigDecimal dlat = new BigDecimal(Math.PI / 180).multiply(new BigDecimal(EARTH_RADIUS));
        // 半径/弧度radius对应的圆心角/纬度
        double α = new BigDecimal(radius).divide(dlat, DEFAULT_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        double latN = lat + α;
        double latS = lat - α;
        // β=180/πr * radius 而r=R*cosα 故 β=radius/(dlat*cosα)
        double β = new BigDecimal(radius).divide(dlat.multiply(new BigDecimal(Math.cos(α))), DEFAULT_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        double lonE = lon + β;
        double lonW = lon - β;
        return new double[]{lonW, lonE, latS, latN};
    }

    /**
     * @throws
     * @方法名：checkPosition
     * @功能描述：计算两点距离 大于半径的返回false
     * @创建人：leo
     * @创建时间：2012-12-6 下午5:06:31
     * @参数：@param lon
     * @参数：@param lat
     * @参数：@param lonx
     * @参数：@param latx
     * @参数：@param radius
     * @参数：@return
     * @返回：boolean
     */
    public static boolean checkPosition(double lon, double lat, double lonx, double latx, int radius) {
        double distance = 0.0;
        double dLat = Double.valueOf(new BigDecimal(String.valueOf((latx - lat))).multiply(new BigDecimal(String.valueOf(Math.PI))).divide(new BigDecimal(String.valueOf(180)), DEFAULT_SCALE, BigDecimal.ROUND_HALF_EVEN).toString());
        double dLon = Double.valueOf(new BigDecimal(String.valueOf((lonx - lon))).multiply(new BigDecimal(String.valueOf(Math.PI))).divide(new BigDecimal(String.valueOf(180)), DEFAULT_SCALE, BigDecimal.ROUND_HALF_EVEN).toString());
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(latx * Math.PI / 180) * Math.cos(lat * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        distance = (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))) * EARTH_RADIUS;
        double res = Double.valueOf(String.valueOf(radius));
        return distance > res ? false : true;
    }

    public static double[] getAround1(double lat, double lon, int raidus) {

        Double latitude = lat;
        Double longitude = lon;

        Double degree = (24901 * 1609) / 360.0;
        double raidusMile = raidus;

        Double dpmLat = 1 / degree;
        Double radiusLat = dpmLat * raidusMile;
        Double minLat = latitude - radiusLat;
        Double maxLat = latitude + radiusLat;

        Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
        Double dpmLng = 1 / mpdLng;
        Double radiusLng = dpmLng * raidusMile;
        Double minLng = longitude - radiusLng;
        Double maxLng = longitude + radiusLng;
        return new double[]{minLat, minLng, maxLat, maxLng};
    }

    /**
     * 根据两点间经纬度坐标（double值），计算两点间距离，单位为米
     *
     * @param lng1
     * @param lat1
     * @param lng2
     * @param lat2
     * @return
     */
    public static boolean getDistance(double lng1, double lat1, double lng2, double lat2, Integer radius) {
        double radLat1 = lat1 * RAD;
        double radLat2 = lat2 * RAD;
        double a = radLat1 - radLat2;
        double b = (lng1 - lng2) * RAD;
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s > radius ? false : true;
    }

    public static void ObjectToObject(Object resource, Object destination) throws Exception {
        if (null == resource)
            throw new ServiceException("参数不能为空");
        Field[] fields = resource.getClass().getDeclaredFields();
        Field dfield = null;
        boolean accessible = false;
        boolean dAccessible = false;
        for (Field field : fields) {
            String attrName = field.getName();
            accessible = field.isAccessible();
            field.setAccessible(true);
            dfield = destination.getClass().getDeclaredField(attrName);
            dAccessible = dfield.isAccessible();
            dfield.setAccessible(true);
            dfield.set(destination, field.get(resource));
            dfield.setAccessible(dAccessible);
            field.setAccessible(accessible);
        }
    }

    /**
     * @param str 需处理的数值
     * @return
     * @描述 数值后面小数点的处理 针对以下情况 "20.0000 20.00100  20.1111 20.11011 2. 20 20%"
     * 去除小数点后面的0 全0则保留两位
     * @auther lailin
     * @date 2013-11-29 上午10:57:27
     */
    public static String numericalTreatment(String str) {
        // 当前通过情况 "20.0000  20.00100  20.1111 20.11011 2. 20 20%";
        try {
            if (null != str && !"".equals(str)) {
                if (str.lastIndexOf(".") == str.length() - 1) {
                    return str + "00";
                } else {
                    String afterPointNum = str.substring(str.indexOf(".") + 1, str.length());
                    String strLastChar = String.valueOf(afterPointNum.charAt(afterPointNum.length() - 1));
                    boolean isNum = true;
                    DecimalFormat df = new DecimalFormat("0.00");
                    if (!strLastChar.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$")) {
                        str = str.substring(0, str.length() - 1);
                        afterPointNum = afterPointNum.substring(0, afterPointNum.length() - 1);
                        isNum = false;
                    }
                    str = (Integer.parseInt(afterPointNum) == 0 || -1 == str.indexOf(".") || str.lastIndexOf(".") == str.length() - 1) ? df.format(Double.parseDouble(str)) : str.substring(0, str.indexOf(".") + 1) + afterPointNum.replaceAll("0*$", "");
                    str = (str.substring(str.indexOf(".") + 1, str.length() - 1).length()) < 2 ? df.format(Double.parseDouble(str)) : str;
                    return !isNum ? (str + strLastChar) : str;
                }
            }
            return null;
        } catch (NumberFormatException e) {
            logger.info("数值转换失败,无法识别的数据类型【" + str + "】");
            return null;
        }
    }

  

    /**
     * @throws
     * @方法名：randomInt
     * @功能描述：生成随机数
     * @创建人：leo
     * @创建时间：2012-8-10 上午11:39:57
     * @参数：@param places 随机数位数
     * @参数：@return
     * @返回：String
     */
    public static String randomInt(int places) {
        Random r = new Random();
        int randomInt = r.nextInt((int) Math.pow(10, places));
        return String.format("%0" + String.valueOf(places) + "d", randomInt);
    }

    /**
     * @throws
     * @方法名：getStrLength
     * @功能描述：获取字符串长度
     * @创建人：leo
     * @创建时间：2012-9-6 下午4:31:22
     * @参数：@param message
     * @参数：@return
     * @返回：Integer
     */
    public static Integer getStrLength(String message) {
        message = message.replaceAll("[^\\x00-\\xff]", "**");
        int length = message.length();
        return length;
    }

    /**
     * 计算打折的金额（保留0位小数，四舍五入）
     *
     * @param amount        打折前的金额
     * @param discountValue 折扣值，9折为90,85折为85
     * @return
     */
    public static Long calDiscountAmount(Long amount, Long discountValue) {
        BigDecimal totalAmount = new BigDecimal(amount);
        BigDecimal discount = new BigDecimal(discountValue);
        return totalAmount.multiply(discount).divide(BigDecimal.valueOf(100L), 0, BigDecimal.ROUND_HALF_UP).longValue();
    }

    public static Long calDiscountAmount(BigDecimal amount, Long discountValue) {
        BigDecimal discount = new BigDecimal(discountValue);
        return amount.multiply(discount).divide(BigDecimal.valueOf(100L), 0, BigDecimal.ROUND_HALF_UP).longValue();
    }

    public static Long reduceFee(long amount, long totalAmount, long fee) {
        BigDecimal bAmount = new BigDecimal(amount);
        BigDecimal btAmount = new BigDecimal(totalAmount);
        BigDecimal bFee = new BigDecimal(fee);
        BigDecimal result = bAmount.subtract(bFee.multiply(bAmount.divide(btAmount, 2, RoundingMode.UP))).setScale(0, RoundingMode.UP);
        return result.longValue();
    }

    /**
     * 积分 转 元(单位:分)
     * 1积分=0.5分钱
     * 100积分=50分=0.5元
     *
     * @param amount
     * @return
     */
    public static Long discountPointCalculation(Long amount) {
        BigDecimal point = new BigDecimal(amount);
        BigDecimal discount = new BigDecimal(0.5);
        return point.multiply(discount).longValue();
    }

    /**
     * 获取随机字母字符串
     *
     * @param length
     * @return
     */
    public static String getRandomString(int length) { //length表示生成字符串的长度
        String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static String strFenToYuan(String fen) {
        if (StringUtils.isBlank(fen)) {
            return "0.00";
        }
        BigDecimal ret = new BigDecimal(fen).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
        return ret.toString();
    }

    public static String strYuanToFen(String yuan) {
        if (StringUtils.isBlank(yuan)) {
            return "0";
        }
        BigDecimal ret = new BigDecimal(yuan).multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP);
        return ret.toString();
    }

    /**
     * "1,2,3" -> [1,2,3]
     * @param str "1,2,3"
     * @param splitChar
     * @return [1,2,3]
     */
    public static long[] splitToArray(String str, String splitChar) {
        if (str == null) {
            throw new NullPointerException("str can not be null.");
        }
        String[] arr = str.split(splitChar);
        long[] ret = new long[arr.length];
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            ret[i] = Long.valueOf(s.trim());
        }
        return ret;
    }
}
